Unit Comptes;

Interface
Uses 
	Types;

//Retourne l'indice du compte de notre collection	
FUNCTION indiceCompte(ID_Compte:INTEGER ; collectionCompte : TTabCompte) : INTEGER;

//Crée un nouveau compte à notre client
PROCEDURE creationCompte(ID_Client : INTEGER; VAR collectionCompte : TTabCompte );

//Effectue un virement 
PROCEDURE virement(ID_Compte : INTEGER; VAR collectionCompte : TTabCompte);

//Clôture un compte
PROCEDURE cloture(ID_Compte : INTEGER ; VAR collectionCompte : TTabCompte);

//Affiche tous les comptes de notre client
PROCEDURE afficheComptes(ID_client:INTEGER; collectionCompte:TTabcompte);

//Ajoute un compte dans notre collection
PROCEDURE addCompte(VAR tabCompte : TTabCompte; compte : TCompte);

//Effecture un dépot
PROCEDURE depot(ID_Compte : INTEGER;  VAR collectionCompte : TTabCompte);

//Effectue un retrait
PROCEDURE retrait(ID_Compte : INTEGER;  VAR collectionCompte : TTabCompte);

//Retourne le compte présent à la case i de la collection
FUNCTION findCompte(collectionCompte : TTabCompte; i:INTEGER) : TCompte;

//Calcule le nombre de compte(s) qu'a notre client	
FUNCTION nombreCompte(ID_client : INTEGER; collectionCompte : TTabcompte): INTEGER;

//Retourne les informations du compte	
PROCEDURE afficheCompte(ID_Compte : INTEGER ; collectionCompte : TTabCompte);
			
IMPLEMENTATION

//Ajoute un compte dans notre collection
PROCEDURE addCompte(VAR tabCompte : TTabCompte; compte : TCompte);

	Begin
		tabCompte.nbcompte += 1;
		tabCompte.IDListCompte += 1;
		compte.IDCompte := tabCompte.IDListCompte;
		tabCompte.tabcompte[tabCompte.nbcompte]:=compte;
	End;
	
//Retourne l'indice du compte de notre collection	
FUNCTION indiceCompte(ID_compte : INTEGER ; collectionCompte : TTabCompte) : INTEGER;

	Var
	i : INTEGER;
	
	Begin
		i:=1;
		//WHILE( i > collectionCompte.nbcompte) OR (ID_compte <> collectionCompte.tabcompte[i].IDcompte) DO
		WHILE( i <= collectionCompte.nbcompte) AND (ID_compte <> collectionCompte.tabcompte[i].IDcompte) DO
			begin
				i:=i + 1;
			end;	
																									//Boucle qui compare notre ID_Compte à l'ID_Compte de notre tableau et s'arrête sitôt qu'on se trouve à la hauteur de l'enregistrement
		IF(i > collectionCompte.nbcompte) THEN
			i:=-1;																					//Si à la fin de la boucle il n'a tjrs pas trouvé il donne la valeur -1 pour définir un cas de sortie
		indiceCompte:=i;																			//Retourne l'indice du tableau où s'est arrêter notre boucle
	END;

//Crée un nouveau compte à notre client
PROCEDURE  creationCompte(ID_Client : INTEGER; VAR collectionCompte : TTabCompte );

	VAR 
		compte : Tcompte;
		choixTaux : INTEGER;
		choixType : STRING;
		
	BEGIN
		compte.libelle:='';
		compte.taux:=0;
		compte.solde:=-1;
		compte.limite:=1;																			//initialise compte
		
		compte.IDcompte:= collectionCompte.IDListcompte;											//Attribution automatique de la nouvelle entrée à la var compte.IDcompte en prenant le dernier IDListcompte
		compte.IDclient := ID_Client;																//Attribution de l'ID_Client à notre var compte.IDclient
		
		WHILE(compte.libelle = '') DO																//Définition du types au moyen d'un case
		BEGIN		
			WRITELN('Entrez le type de compte : ');
			WRITELN('1. Courant');
			WRITELN('2. Epargne');
			READLN (choixType);
			CASE (choixType) OF
					'1':
						begin
							compte.Libelle := 'Courant';
						end;
					'2':
						begin
							compte.Libelle := 'Epargne';
						end;
			end;

		END;//compte.libelle = ''

		WHILE(compte.taux = 0) DO																	//Définition du taux au moyen d'un case
		BEGIN		
			WRITELN('Entrez le taux du compte : ');
			WRITELN('1. 0.5%');
			WRITELN('2. 1.5%');
			WRITELN('3. 2.5%');
			WRITELN('4. 5%');
			READLN(choixTaux);
			CASE (choixTaux) OF
					1:
						begin
							compte.taux := 0.5;
						end;
					2:
						begin
							compte.taux := 1.5;
						end;
					3:
						begin
							compte.taux := 2.5;
						end;
					4:
						begin
							compte.taux := 5;
						end;
			end;

		END;//compte.taux = 0
			
		WHILE(compte.solde = -1) DO
		BEGIN
				WRITE('Entrez le solde initiale du compte :');										//Définition du solde initial
				READLN(compte.solde);
				IF (compte.solde = -1) THEN
					WRITELN('Il est obligatoire de saisir un solde!');
		END;
																				
		
		WHILE(compte.limite = 1) DO																	//Définition de la limite 
		BEGIN		
			WRITE('Entrez la limite de retrait du compte, rentrer en positif :');
			READLN(compte.limite);
			IF (compte.limite = 1) THEN
				WRITELN('Il est obligatoire de saisir une limite!');
		END;	
		addCompte(collectionCompte, compte);
END;

//Effectue un virement 
PROCEDURE virement(ID_Compte : INTEGER; VAR collectionCompte : TTabCompte);

	Var
		limite : REAL;
		solde : REAL;
		montant: INTEGER;
		i: INTEGER;
		transaction : boolean;
		compte2 : INTEGER;
		indicecompte2 : INTEGER;
		
	begin	
		transaction := False;  
		i :=indiceCompte(ID_Compte,collectionCompte) ; 												//Fait appel à la fonction indiceCompte afin de connaître l'emplacement dans la collectionCompte
		solde := collectionCompte.tabcompte[i].solde;												//On charge le solde du compte
		limite := collectionCompte.tabcompte[i].solde + collectionCompte.tabcompte[i].limite;		//On ajoute l emontant de la limite au solde afin d'obtenir le retrait max
		WRITELN('Votre solde est de : ',solde:0:2);													//On affiche des informations pour réduire la possiblité d'erreur de saisie
		WRITELN('Vous pouvez virer au maximum : ',limite:0:2);											
		WHILE (NOT transaction) DO
			begin
				WRITELN('Quel montant desirez-vous virer?');
				READLN(montant);
					IF (montant > limite) THEN
						WRITELN('La somme que vous desirez virer est trop elevee')					//test qui vérifie qu'on retire pas plus que ce qu'on peut
					ELSE
						begin
							collectionCompte.tabcompte[i].solde := collectionCompte.tabcompte[i].solde - montant;
							transaction := true;
						end;
			end;																					//Boucle qui demande le montant à virer et qui contrôle que ce soit bien possible en tenant compte de la limite du compte
		WRITELN('Entrer le compte client a crediter: ');
		READLN(compte2);																			//On entre les infos du compte destinataire, (on sous-entend qu'on connait le numéro de compte . On pourrait améliorer en ajouter une fonction de recherche avec des autres infors que son numéro de compte
		indicecompte2:=indicecompte(compte2,collectionCompte); 										//Recherche l'indice du 2 compte
		IF (indicecompte2<>-1) THEN
			collectionCompte.tabcompte[indicecompte2].solde := collectionCompte.tabcompte[indicecompte2].solde + montant;
		WRITELN('Votre nouveau solde est de : ',collectionCompte.tabcompte[i].solde:0:2);
		WRITELN('Taper ENTER pour continuer');
		READLN();
	end;
	
//Cloture un compte	
PROCEDURE cloture(ID_Compte : INTEGER ; VAR collectionCompte : TTabCompte);							

	Var
		i :	INTEGER;
		confirmation : STRING;
		choix : STRING;
		
	Begin
			confirmation := 'O';
			i := indiceCompte(ID_Compte,collectionCompte);											//Fait appel à la fonction indiceCompte afin de connaître l'emplacement dans la collectionCompte
			WRITELN('Le solde de votre compte est de : ',collectionCompte.tabcompte[i].solde:0:2);
			WRITELN('');
			WRITE('Etes-vous sur de vouloir supprimer ce compte : O/N : ');							//Demande de confirmation de suppression
			READ (choix);
			IF (choix = confirmation) THEN	
				begin
					WHILE (i <= collectionCompte.nbcompte) DO
						begin
							collectionCompte.tabcompte[i]:= collectionCompte.tabcompte[i+1];
							i:=i+1;
						end;
					collectionCompte.nbcompte := collectionCompte.nbcompte - 1;
					WRITELN('');																	//Le compte à supprimer est ecrasé par le suivant et on fait directement																				//un tri pour que le tableau corresponde au nbcompte
					WRITELN('Ce compte a ete supprime');
					WRITELN('');
					WRITELN('Taper ENTER pour continuer');
					READLN();
				end;//choix = confirmation
	END;
	
//Affiche tous les comptes de notre client	
PROCEDURE afficheComptes(ID_client:INTEGER; collectionCompte:TTabcompte);

	VAR
		i:INTEGER;
		j:INTEGER;
		comptepos:INTEGER;
		
	BEGIN
		i := ID_client;																				//On affiche tous les comptes et leurs infos ainsi que le nombre de compte que le client a
		j := 1;
		comptepos := 0;
		WHILE(j <= collectionCompte.nbcompte) DO
			BEGIN
				IF(i = collectionCompte.tabcompte[j].IDclient) THEN
					BEGIN
						WRITELN('---------------------------------------------------');
						WRITELN('ID compte : ', collectionCompte.tabcompte[j].IDcompte);
						WRITELN('Libelle : ', collectionCompte.tabcompte[j].Libelle);
						WRITELN('Taux : ', collectionCompte.tabcompte[j].taux:0:1,'%');
						WRITELN('Solde : ',collectionCompte.tabcompte[j].solde:0:2);
						WRITELN('Limite de retrait : -',collectionCompte.tabcompte[j].limite:0:2);
						WRITELN('Indice compte : ',j);
						WRITELN('---------------------------------------------------');
						WRITELN('');
						
						comptepos := comptepos + 1;
						
					END;
					j := j + 1;		
			END;//j <= collectionCompte.nbcompte
			WRITELN('Ce client possede ',comptepos,' compte(s)');
			WRITELN('');
	END;
		
//Effectue un dépot
PROCEDURE depot (ID_Compte : INTEGER;  VAR collectionCompte : TTabCompte);							//Définition du nom de notre procédure ainsi que ses paramètres en entrée-sortie
 
Var
	montant: REAL;
	i: integer;
	
BEGIN 	    
		i :=indiceCompte(ID_Compte,collectionCompte); 												//Fait appel à la fonction indiceCompte afin de connaître l'emplacement dans la collectionCompte
		WRITELN('Entrer le montant a deposer : ');
		READLN(montant);
        collectionCompte.tabcompte[i].solde := collectionCompte.tabcompte[i].solde + montant;
		WRITELN('Votre nouveau solde est de : ',collectionCompte.tabcompte[i].solde:0:2);
		WRITELN('Taper ENTER pour continuer');
		READLN();																					//Modification et affichage du solde
END;

//Effectue un retrait
PROCEDURE retrait(ID_Compte : INTEGER;  VAR collectionCompte : TTabCompte);						
 
	Var
		limite : REAL;
		solde : REAL;
		montant: REAL;
		i: INTEGER;
		transaction : boolean;
		
	BEGIN 
			transaction := False;  
			i :=indiceCompte(ID_Compte,collectionCompte) ; 											//Fait appel à la fonction indiceCompte afin de connaître l'emplacement dans la collectionCompte
			solde := collectionCompte.tabcompte[i].solde;											//On charge le solde du compte
			limite := collectionCompte.tabcompte[i].solde + collectionCompte.tabcompte[i].limite;	//On ajoute l emontant de la limite au solde afin d'obtenir le retrait max
			WRITELN('Votre solde est de : ',solde:0:2);												//On affiche des informations pour réduire la possiblité d'erreur de saisie
			WRITELN('Vous pouvez retirer au maximum : ',limite:0:2);									
			WHILE (NOT transaction) DO
				begin
					WRITELN('Quel montant desirez-vous retirer?');
					READLN(montant);
						IF (montant > limite) THEN
							WRITELN('La somme que vous desirez retirer est trop elevee')			//test qui vérifie qu'on retire pas plus que ce qu'on peut
						ELSE
							begin
								collectionCompte.tabcompte[i].solde := collectionCompte.tabcompte[i].solde - montant;
								transaction := true;
								WRITELN('Votre nouveau solde est de : ',collectionCompte.tabcompte[i].solde:0:2); //Si solde est suffisant on le soustrait et réaffiche le solde
								WRITELN('Taper ENTER pour continuer');
								READLN();
							end;
				end;//NOT transaction
	END;

//Retourne le compte présent à la case i de la collection
FUNCTION findCompte(collectionCompte : TTabCompte; i : INTEGER) : TCompte;

	begin
		IF (i<1) OR (i>collectionCompte.nbcompte) THEN
			begin
				findCompte.IDcompte := 0;															//En connaissante l'emplacement du compte dans le tableau, on charge les infos du compte dans la fonction
				findCompte.IDclient:= 0;
				findCompte.Libelle:= '';
				findCompte.taux:= 0;
				findCompte.solde:= 0;
				findCompte.limite:= 0;
			end
		ELSE
			findCompte := collectionCompte.tabcompte[i];
	end;

//Calcule le nombre de compte(s) qu'a notre client	
FUNCTION nombreCompte(ID_Client : INTEGER; collectionCompte : TTabcompte): INTEGER;

	VAR
		i:INTEGER;
		j:INTEGER;
		comptepos:INTEGER;
			
	BEGIN
		i := ID_Client;																				//On charge dans i l'emplacement du client et à chaque fois qu'on trouve un compte on incrémente
		j := 1;
		comptepos := 0;
		WHILE(j <= collectionCompte.nbcompte) DO
			BEGIN
				IF(i = collectionCompte.tabcompte[j].IDclient) THEN
					BEGIN					
						comptepos := comptepos + 1;					
					END;
					j := j + 1;		
			END;
			nombreCompte := comptepos;																//Le nombre de compte qu'on a trouvé est chargé dans la fonction nombreCompte
	END;
	
//Retourne les information du compte	
PROCEDURE afficheCompte(ID_Compte : INTEGER ; collectionCompte : TTabCompte);		
																		
	Var 
		i : INTEGER;
		
	Begin 
		i := indiceCompte(ID_Compte,collectionCompte);												//On recherche l'emplacement du compte dans le tableau et on affiche ses informations
		WRITELN('ID client : ',collectionCompte.tabcompte[i].IDclient);																
		WRITELN('ID compte  : ',collectionCompte.tabcompte[i].IDcompte);
		WRITELN('Libelle : ',collectionCompte.tabcompte[i].Libelle);
		WRITELN('Taux : ',collectionCompte.tabcompte[i].taux:0:1,'%');
		WRITELN('Solde : ',collectionCompte.tabcompte[i].solde:0:2);
		WRITELN('Limite de retrait: -',collectionCompte.tabcompte[i].limite:0:2);
		WRITELN('');
	End;
END.
